package cn.cosmosx.base.config.swagger;

import cn.cosmosx.base.dict.ApiDict;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import springfox.documentation.builders.PropertySpecificationBuilder;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin;
import springfox.documentation.spi.schema.contexts.ModelPropertyContext;

import java.lang.reflect.Field;

/**
 * swagger3 自定义展示枚举类型信息
 *
 * @author gengzhy
 * @since 2022-9-27
 */
@Slf4j
@Component
public class DictPropertyPlugin implements ModelPropertyBuilderPlugin {

    @Override
    public void apply(ModelPropertyContext context) {
        if (context.getBeanPropertyDefinition().isPresent()) {
            Class<?> rawPrimaryType = context.getBeanPropertyDefinition().get().getRawPrimaryType();
            // 枚举字典实现接口ApiDict且是Enum类型的才处理
            if (ApiDict.class.isAssignableFrom(rawPrimaryType) && Enum.class.isAssignableFrom(rawPrimaryType)) {
                if (rawPrimaryType.getEnumConstants() == null) {
                    return;
                }
                String description = "";
                try {
                    // 拼接枚举属性注释
                    ApiDict[] constants = (ApiDict[]) rawPrimaryType.getEnumConstants();
                    StringBuilder builder = new StringBuilder();
                    for (ApiDict dict : constants) {
                        Enum<?> eDict = (Enum<?>) dict;
                        builder.append(eDict.name()).append("(").append(dict.getCode()).append("-").append(dict.getDesc()).append("),");
                    }
                    if (builder.length() > 0) {
                        builder.insert(0, "{");
                        description = builder.substring(0, builder.length() - 1) + "}";
                    }
                    Field mField = PropertySpecificationBuilder.class.getDeclaredField("description");
                    mField.setAccessible(true);
                    // context 中的 builder 对象保存了字段的信息
                    description = mField.get(context.getSpecificationBuilder()) + description;
                } catch (Exception e) {
                    log.error("字典值处理失败", e);
                    return;
                }
                context.getSpecificationBuilder().description(description);
            }
        }
    }

    @Override
    public boolean supports(DocumentationType documentationType) {
        return true;
    }
}
